/*
 * @Author: ischen.x ischen.x@foxmail.com
 * @Date: 2024-07-19 15:24:04
 * @LastEditors: ischen.x ischen.x@foxmail.com
 * @LastEditTime: 2024-07-22 13:28:53
 * 
 * Copyright (c) 2024 by fhchengz, All Rights Reserved. 
 */

#include "DS1339.h"

/**
 * @description: I2C write interface
 * @param reg_addr: Register address
 * @param data: write data
 * @param length: write length
 * @return 0: successful
 */
static int (*ds1339_i2c_mem_write)(uint8_t reg_addr, uint8_t *data, uint8_t length);

/**
 * @description: I2C read interface
 * @param reg_addr: Register address
 * @param data: read data
 * @param length: read length
 * @return 0: successful
 */
static int (*ds1339_i2c_mem_read)(uint8_t reg_addr, uint8_t *data, uint8_t length);

int ds1339_set_read_write_function(int(*read)(uint8_t, uint8_t *, uint8_t), int(*write)(uint8_t, uint8_t *, uint8_t))
{
    if (read && write) {
        ds1339_i2c_mem_read = read;
        ds1339_i2c_mem_write = write;
        return 0;
    } else {
        return -1;
    }
}

static uint8_t val_to_bcd(uint8_t val)
{
    return (val / 10 * 16 + val % 10);
}

static uint8_t bcd_to_dec(uint8_t bcd)
{
    return (10 * (bcd>>4) + (bcd & 0x0F));
}

static int ds1339_get_reg(ds1339_reg_type *reg)
{
    return ds1339_i2c_mem_read(0x00, (uint8_t *)reg, sizeof(ds1339_reg_type));
}

int ds1339_get_time(struct tm *time_struct)
{
    int ret = 0;
    ds1339_reg_type reg = {0};
    ret = ds1339_get_reg(&reg);
    if (ret == 0) {
        time_struct->tm_sec  = bcd_to_dec(reg.Seconds & 0x7F);
        time_struct->tm_min  = bcd_to_dec(reg.Minutes & 0x7F);
        time_struct->tm_hour = bcd_to_dec(reg.Hours & 0x3F);
        time_struct->tm_mday = bcd_to_dec(reg.Date & 0x3F);
        time_struct->tm_mon  = bcd_to_dec(reg.Mounth_Century & 0x1F) - 1;
        time_struct->tm_wday = bcd_to_dec(reg.Day & 0x07);
        time_struct->tm_year = bcd_to_dec(reg.year) + 2000 - 1900; 
    } 
    return ret;
}

int ds1339_set_time(struct tm *time_struct)
{
    int ret = 0;
    ds1339_reg_type reg = {
        .Seconds =         val_to_bcd(time_struct->tm_sec ),
        .Minutes =         val_to_bcd(time_struct->tm_min ),
        .Hours =           val_to_bcd(time_struct->tm_hour),
        .Day =             val_to_bcd(time_struct->tm_wday),
        .Date =            val_to_bcd(time_struct->tm_mday ),
        .Mounth_Century = val_to_bcd(time_struct->tm_mon + 1),
        .year =            val_to_bcd(time_struct->tm_year - 2000 + 1900),
    };
    ret = ds1339_i2c_mem_write(0x00, (uint8_t *)&reg, 7);
    return ret;
}

